package sunlight.criptography;

import java.security.Provider;

import org.jasypt.digest.config.DigesterConfig;
import org.jasypt.digest.config.SimpleDigesterConfig;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.salt.FixedStringSaltGenerator;
import org.jasypt.salt.SaltGenerator;
import org.jasypt.util.password.ConfigurablePasswordEncryptor;

public class Cryptographer {
	
	private Provider Provider;
	private String   Key;		
	private String 	 Algorithm;
	
	private int 	 	  SaltIterations;
	private SaltGenerator SaltGenerator;
	
	private DigesterConfig DigesterConfiguration; 
	
	protected static String[] ReccomendedAlgorithms = new String[]{"PBEWITHSHA256AND128BITAES-CBC-BC", "SHA-256"};
	
	public Cryptographer(Provider JCEProvider){
		this.Provider = JCEProvider; 
		
		this.Key 			= String.valueOf(Math.random() * 28000);
		this.Algorithm		= Cryptographer.ReccomendedAlgorithms[0];
		this.SaltIterations = 1000;
		this.SaltGenerator	= new FixedStringSaltGenerator();
	}
	
	public Cryptographer(Provider JCEProvider, String key){
		this.Provider = JCEProvider; 
		this.Key 	  = key;
		
		this.Algorithm		= Cryptographer.ReccomendedAlgorithms[0];
		this.SaltIterations = 1000;
		this.SaltGenerator	= new FixedStringSaltGenerator();
	}
	
	public Cryptographer(Provider JCEProvider, String key, String algorithm){
		this.Provider 		= JCEProvider; 
		this.Key 	  		= key;
		this.Algorithm		= algorithm;
		this.SaltIterations = 1000;
		this.SaltGenerator	= new FixedStringSaltGenerator();
	}
	
	public Cryptographer(Provider JCEProvider, String key, String algorithm, int saltIterations){
		this.Provider 		= JCEProvider; 
		this.Key 	  		= key;
		this.Algorithm		= algorithm;
		this.SaltIterations = saltIterations;
	}
	
	public Cryptographer(Provider JCEProvider, String key, String algorithm, int saltIterations, SaltGenerator saltGen){
		this.Provider 		= JCEProvider; 
		this.Key 	  		= key;
		this.Algorithm		= algorithm;
		this.SaltIterations = saltIterations;
		this.SaltGenerator 	= saltGen;
	}
	
	public void setProvider(Provider JCEProvider){
		this.Provider = JCEProvider;
	}
	
	public Provider getProvider(){
		return this.Provider;
	}
	
	public void setKey(String key){
		this.Key = key;
	}
	
	public String getKey(){
		return this.Key;
	}
	
	public void setAlgorithm(String algorithm){
		this.Algorithm = algorithm;
	}
	
	public String getAlgorithm(){
		return this.Algorithm;
	}
	
	public void setSaltIterations(int iterations){
		this.SaltIterations = iterations;
	}
	
	public int getSaltIterations(){
		return this.SaltIterations;
	}
	
	public String encrypt(String message){
		StandardPBEStringEncryptor Encryptor = new StandardPBEStringEncryptor();
		
		Encryptor.setProvider(this.Provider);
		Encryptor.setAlgorithm(this.Algorithm);
		Encryptor.setPassword(this.Key);
		
		Encryptor.initialize();

		return Encryptor.encrypt(message);
	}
	
	public String decrypt(String message){
		StandardPBEStringEncryptor Encryptor = new StandardPBEStringEncryptor();
		
		Encryptor.setProvider(this.Provider);
		Encryptor.setAlgorithm(this.Algorithm);
		Encryptor.setPassword(this.Key);
		
		Encryptor.initialize();

		return Encryptor.decrypt(message);
	}
	
	public String encryptPassword(String password, DigesterConfig Config){
		this.DigesterConfiguration = Config;
		
		ConfigurablePasswordEncryptor Encryptor = new ConfigurablePasswordEncryptor();
		
		Encryptor.setConfig(Config);
		
		return Encryptor.encryptPassword(password);
	}
	
	public String encryptPassword(String password){
		SimpleDigesterConfig config = new SimpleDigesterConfig();
		
		config.setProvider(this.Provider);
		config.setAlgorithm(this.Algorithm);
		config.setIterations(this.SaltIterations);
		config.setSaltGenerator(this.SaltGenerator);
		
		this.DigesterConfiguration = config;
		
		return this.encryptPassword(password, config);
	}
	
	public boolean checkPassword(String plain, String encrypted){
		ConfigurablePasswordEncryptor Encryptor = new ConfigurablePasswordEncryptor();
		Encryptor.setConfig(this.DigesterConfiguration);
		
		return Encryptor.checkPassword(plain, encrypted);
	}

	public static String[] getReccomendedAlgorithms() {
		return ReccomendedAlgorithms;
	}
}
